package com.base.app_core.base.impl;


import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import com.base.app_core.util.XYBAUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by xiangheng.song on 2017/3/1.
 */

public abstract class BaseAdapter<T, V> extends android.widget.BaseAdapter {

    protected Context context;
    private List<T> list;

    private static final Map<Class<?>, Constructor<? extends BaseViewHolder>> VIEW_HOLDER_MAPPING = new HashMap<>();
    private static final Set<Class> INNER_CLASS_SET = new HashSet<>();

    public BaseAdapter(Context context, List<T> list){
        this.context = context;
        this.list = list;
        XYBAUtils.bind(this);
    }

    public Context getContext() {
        return context;
    }

    public BaseAdapter(Context context, T... array){
        this(context, Arrays.asList(array));
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    public List<T> getList() {
        return list;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    public T getObject(int i){
        return (T) getItem(i);
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        Object holder;
        if(view == null){
            view = View.inflate(context, getItemLayoutId(), null);
            holder = createViewHolder(this, view);
            view.setTag(holder);
        }else{
            holder = view.getTag();
        }

        T item = (T) getItem(i);
        fillData(item, (V) holder);
        return view;
    }

    protected abstract void fillData(T item, V holder);

    protected abstract int getItemLayoutId();

    private static Object createViewHolder(BaseAdapter adapter, View view) {
        Class<?> adapterClass = adapter.getClass();
        Constructor constructor = VIEW_HOLDER_MAPPING.get(adapterClass);
        boolean isInnerClass = INNER_CLASS_SET.contains(adapterClass);
        if(constructor == null){
            try {
                Class<?> viewHolderClass = (Class<?>) ((ParameterizedType) adapterClass.getGenericSuperclass()).getActualTypeArguments()[1];
                isInnerClass = viewHolderClass.getName().contains("$");
                if(isInnerClass){
                    // 内部类构造方法第一个参数是外部类的对象
                    constructor = viewHolderClass.getConstructor(adapter.getClass(), View.class);
                    INNER_CLASS_SET.add(adapterClass);
                }else{
                    constructor = viewHolderClass.getConstructor(View.class);
                }
                VIEW_HOLDER_MAPPING.put(adapterClass, constructor);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            if(isInnerClass){
                return constructor.newInstance(adapter, view);
            }
            return constructor.newInstance(view);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
